package org.flexthinker.binding.validation.support
{
    import org.flexthinker.binding.form.FormModel;

    import org.flexthinker.binding.validation.FormModelValidator;

    import org.flexthinker.binding.validation.ValidationResults;

    import mx.events.ValidationResultEvent;
    import mx.validators.Validator;

    /**
     * This class receives a formModel and a set of rules ( collection of <code>Validator</code> objects )
     * and validates the provided formModel with the given validators.
     */
    public class RulesValidator extends Validator implements FormModelValidator
    {
        private var formModel:FormModel;

        private var validators:Vector.<Validator> = new Vector.<Validator>();


        public function RulesValidator( validators:Vector.<Validator> = null ):void
        {
            super();
            if ( validators )
            {
                this.validators = validators;
            }
        }

        /**
         * The form model to validate
         * @return FormModel instance
         */
        public function getFormModel():FormModel
        {
            return formModel;
        }


        public function setFormModel( value:FormModel ):void
        {
            if( value )
            {
                this.formModel = value;
            }
        }

        public function setValidators( value:Vector.<Validator> ):void
        {
            this.validators = value;
        }


        public function addPropertyValidator( validator:Validator ):void
        {
            validators.push( validator );
        }


        public function removePropertyValidator( validator:Validator ):void
        {
            var idx:int = validators.indexOf( validator );
            if( idx >= 0 )
            {
                validators.splice( idx, 1 );
            }
        }

        public function validateProperty( propertyName:String = null ):ValidationResults
        {
            if( propertyName == null )
            {
                return validateAll();
            }
            var results:DefaultValidationResults = new DefaultValidationResults();
            results.addMessage( validateSpecificProperty( propertyName ) );
            return results;
        }

        public function validateAll():ValidationResults
        {
            var results:DefaultValidationResults = new DefaultValidationResults();
            for each ( var prop:String in formModel.getFieldNames() )
            {
                results.addMessage( validateSpecificProperty( prop ) );
            }
            return results;
        }

        private function validateSpecificProperty( propertyName:String ):ValidationResultEvent
        {
            var propertyValidator:Validator = getValidatorForProperty( propertyName );
            if( propertyValidator )
            {
                var vResult:ValidationResultEvent = propertyValidator.validate(getFormModel().getValueModel(propertyName).getValue());
                //fix the case when a validator is not enabled
                if(vResult == null)
                {
                    vResult = new ValidationResultEvent(ValidationResultEvent.VALID);
                }
                vResult.field = propertyName;
                return vResult;
            }
            return null;
        }

        private function getValidatorForProperty( propertyName:String ):Validator
        {
            for each ( var v:Validator in validators )
            {
                if( v.property == propertyName )
                {
                    v.source = formModel.getFormObject();
                    return v;
                }
            }
            return null;
        }
    }
}
